from threading import Lock


class SemaphoreCollect:
    def __init__(self, **arg):
        self.collect = dict()
        for k, v in arg.items():
            self.collect[k] = SemaphoreItem(value=v)

    def acquire(self, name):
        self.collect[name].acquire()

    def release(self, name):
        self.collect[name].release()

    def ready(self, name):
        return self.collect[name].ready


class SemaphoreItem:
    def __init__(self, value=1):
        self.value = value
        self.ready = False
        self.now = value
        self.lock = Lock()
        self.inner_lock = Lock()

    def acquire(self):
        self.lock.acquire()
        if self.ready:
            self.lock.release()

    def add_index(self, index=1):
        with self.inner_lock:
            if not self.ready:
                self.now += index

    def reacquire(self):
        with self.inner_lock:
            self.lock.release()
            self.now = self.value
            self.ready = False
            self.acquire()

    def release(self):
        with self.inner_lock:
            if not self.ready:
                self.now = 0 if self.now - 1 < 0 else self.now - 1
                if self.now <= 0:
                    self.ready = True
                    self.lock.release()
